﻿//-----------------------------------------------------------------------------------
// <copyright file="UnitTestMethodInvoker.cs" company="P.O.S Informatique">
//     Copyright (c) P.O.S Informatique. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------------------
namespace PosInformatique.DevelopmentTools.VisualStudio.TestExtensions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using PosInformatique.Framework;

    /// <summary>
    /// Represents an invoker which execute 
    /// </summary>
    internal sealed class UnitTestMethodInvoker : IDisposable
    {
        /// <summary>
        /// Contains info about the unit test method to execute.
        /// </summary>
        private readonly UnitTestMethodInvokerInfo info;

        /// <summary>
        /// Unit test class instance which contains 
        /// </summary>
        private object unitTestClass;

        /// <summary>
        /// Initializes a new instance of the <see cref="UnitTestMethodInvoker"/> class
        /// with the specified <paramref name="info"/> of the method to invoke.
        /// </summary>
        /// <param name="info">Instance of <see cref="UnitTestMethodInvokerInfo"/> which contains
        /// info about the unit test method to execute.</param>
        public UnitTestMethodInvoker(UnitTestMethodInvokerInfo info)
        {
            ContractHelper.IsNotNull(info);

            this.info = info;

            this.unitTestClass = Activator.CreateInstance(this.info.Method.ReflectedType);
        }

        /// <summary>
        /// Invoke the unit test.
        /// </summary>
        /// <returns>An instance of <see cref="UnitTestMethodInvokerResult"/>
        /// which represents the result of the unit test.</returns>
        public UnitTestMethodInvokerResult Invoke()
        {
            ContractHelper.ReturnNonNull<UnitTestMethodInvokerResult>();

            Exception exception;

            try
            {
                this.info.Method.Invoke(this.unitTestClass, null);
                exception = null;
            }
            catch (TargetInvocationException e)
            {
                exception = e.InnerException;
            }

            /*finally
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }*/

            return new UnitTestMethodInvokerResult(exception);
        }

        /// <inheritdoc />
        public void Dispose()
        {
            IDisposable disposableUnitTestClass;

            disposableUnitTestClass = this.unitTestClass as IDisposable;
            if (disposableUnitTestClass != null)
            {
                disposableUnitTestClass.Dispose();
            }

            this.unitTestClass = null;
        }
    }
}
